#include "appCore.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_common.h"
#include "espressif/esp_common.h"
#include "freertos/portmacro.h"
#include "gpio.h"
#include "spi_flash.h"
#include "spiffs.h"
#include <fcntl.h>
#include "stdio.h"
#include "sysmanage.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "espressif/espconn.h"
#include "wificonfig.h"
#include "epd_show.h"
#include "sysmanage.h"



void spiffs_fs1_init(void)
{
  struct esp_spiffs_config config;
  s32_t result;

  config.phys_size = 512*1024;//文件系统大小
  config.phys_addr = 1024*1024*3;//文件系统开始位置
  config.phys_erase_block = (1024*4);//擦除块大小4K
  config.log_block_size = (1024*4);
  config.log_page_size = 128;
  config.fd_buf_size = 128;
  config.cache_buf_size = (128+32)*8;
  result = esp_spiffs_init(&config);
}

void smartconfig_process(void)
{
  smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS
  wifi_set_opmode(STATION_MODE);
  smartconfig_start(smartconfig_done);
}

#define KeyOutTimeValue      300
BOOL isSmartconfig(void)
{
  struct station_config* config;

  config = (struct station_config *)zalloc(sizeof(struct station_config));//分配资源

  wifi_station_get_config_default(config);//获取FLASH 配置

  free(config);
  if(strlen(config->ssid) == 0)
  {
    return TRUE;
  }

  gpio16_input_conf();

  if(gpio16_input_get() == 0)//按键按下
  {
    u16_t run = 0;
    while(run++ < KeyOutTimeValue)
    {
      gpio16_output_conf();
      gpio16_output_set(1);
      vTaskDelay(10 / portTICK_RATE_MS);

      gpio16_input_conf();
      printf("run=%d %d\r\n",run,gpio16_input_get());
      if(gpio16_input_get() == 1)
      {
        if(run < 200)//更新图片
        {
          //set_key_evt_wakeup();//按键唤醒
          break;
        }
        else //配置WIFI
        {
          gpio16_output_conf();
          gpio16_output_set(1);
          return TRUE;
        }
      }
    }
    if(run >= KeyOutTimeValue)//按键超时进入配置模式
    {
      gpio16_output_conf();
      gpio16_output_set(1);
      return TRUE;		
    }
  }
  gpio16_output_conf();
  gpio16_output_set(1);
  return FALSE;
}

void wifiInitProcess(void)
{
  struct station_config * config;
  wifiConfigDef *wificonfig;
  u16_t outtime = 10*60*5;

  wificonfig = (wifiConfigDef *)getWIFIConfigDat();
  config = (struct station_config *)zalloc(sizeof(struct station_config));//分配资源

  gpio16_output_conf();
  gpio16_output_set(1);
  if(gpio16_input_get() == 0)//按键按下
  {
    set_key_evt_wakeup();//按键唤醒
    send_epd_mail(EPD_EVT_FULLID);//显示带ID图片
  }

  if(isSmartconfig() == TRUE)
  {
    printf("Entry SmartConfig Mode\r\n");
    send_epd_mail(EPD_EVT_FULLID);//显示带ID图片
    send_epd_mail(EPD_EVT_NoneSIMALA);
		save_system_event(0);//清除所有事件
    smartconfig_process();
    while(isSmartconfigFinsh() == 0)
    {
      vTaskDelay(100 / portTICK_RATE_MS);
      outtime--;
      if(outtime == 0)//超时
      {
        printf("Config WIFI OutTime!!!\r\n");
        break;
      }
    }
    send_epd_mail(EPD_EVT_FULL);
    //get_wifi_intension();
    //set_key_evt_wakeup();//按键唤醒
    vTaskDelay(1000 / portTICK_RATE_MS);
  }
  else
  {
    wifi_station_get_config_default(config);//获取FLASH 配置
    wifi_set_opmode(STATION_MODE);//设置模式
    wifi_station_connect();//链接
    //get_wifi_intension();//获取WIFI信号强度
  }


  free(config);//释放资源
}


void setHostName(void)
{
  u8_t *hostName;
  devInfodef *devInfo;
  devInfo = devinfo_get();

  hostName = calloc(1,64);

  sprintf(hostName,"ESL213_%d",devInfo->mac);
  printf("hostName %s\r\n",hostName);
  wifi_station_set_hostname(hostName);
  free(hostName);
}

BOOL check_is_tcp_exp(void)
{
	u32_t value = 0;

	value = load_system_event();
	if(value & EVT_TCP_EXP)
	{
		printf("Is  TCP Exp\r\n");
		value &= ~EVT_TCP_EXP;//清除标记
		save_system_event(value);
		return TRUE;
	}

	return FALSE;
}

void start_sleep_judge_process(void)
{
	u8 run;
	BOOL status;
	
	status = vbat_low_stop_process();
	if(status == TRUE)//需要刷新屏幕
	{
		epd_show_thread_init();//启动显示线程
		run = 200;
		while(run--)
		{
			vTaskDelay(100 / portTICK_RATE_MS);
			if(is_entry_sleep() == 0)
			{
				system_entry_deep_sleep(0);//继续睡觉
			}
		}
		system_entry_deep_sleep(0);//继续睡觉
	}
	else
	{
		system_entry_deep_sleep(0);//继续睡觉
	}
}


static sever_exp_process(void)
{
	BOOL status;

	status = get_rtc_system_event_bit(EVT_SERVER_NOACK);//获取是否为服务器异常
	set_rtc_system_event_bit(EVT_SERVER_NOACK,FALSE);//清除服务器没有应答
	if(status == TRUE)//服务器异常，休眠
	{
		set_rtc_system_event_bit(EVT_NET_EXP,FALSE);//清除网络异常，以免下次刷新屏幕
		system_entry_deep_sleep(60);
	}
	else//
	{

	}
}


static void sleep_wakeup_is(void)
{
  devInfodef *info;
  u16_t surplus;
  u16_t max_surplus;
  u16_t askFail;

  askFail = load_bkp_askfail_num();//查询服务器失败的次数

  gpio16_output_set(1);
  if(gpio16_input_get() == 0)//按键按下必须强制工作，优先级最高
  {
    return;
  }

	sever_exp_process();//检测服务器是否异常

	//检测是否为TCP链接异常重启
	if(check_is_tcp_exp() == TRUE)//优先级第二高
	{
		return;
	}

  info = devinfo_get();
  if(SILENT_MODE_VALUE == info->cycle)//静默模式
  {
	//if(askFail < PROCESS_ERR_MAX)//如果是应为联网失败，暂时不能放弃重试
	{
	//return;
	}
	printf("SILENT_MODE entry sleep");
	//system_entry_deep_sleep(0);//继续睡觉
	set_system_stop_cycle(SILENT_MODE_VALUE);
	start_sleep_judge_process();//根据电压调整休眠
  }

  max_surplus = info->cycle / EPS_MAX_DEELP_SLEEP;//正常最大唤醒次数
  surplus = load_bkp_surplus_ask_num();
  printf("surplus=%d max_surplus=%d\r\n",surplus,max_surplus);
  if((surplus > 0) && (surplus <= max_surplus))//按键极短按、自动唤醒、真的唤醒
  {
    u32_t deelpSleep;

    deelpSleep = load_bkp_deep_sleep_value();//本次睡眠时间
    printf("Surplus Deelp Sleep %d\r\n",deelpSleep);
    deelpSleep -= EPS_MAX_DEELP_SLEEP;
    save_bkp_deep_sleep_value(deelpSleep);
    surplus--;
    save_bkp_surplus_ask_num(surplus);//剩余次数
    if(deelpSleep <= 0) 
    {
      deelpSleep = 1;
    }
    if((askFail > 0) && (askFail < PROCESS_ERR_MAX))//突然出现连不上网络，需要短时间内尝试
    {
      return;
    }
    set_system_stop_cycle(deelpSleep);//缩短时间
    system_entry_deep_sleep(0);//继续睡觉
  }
}

static void exception_process_entry_sleep(u16_t run,u16_t value)
{
	u16 failNum;

	failNum = load_bkp_askfail_num();//失败测试增加
	failNum++;
	save_bkp_askfail_num(failNum);
	run = value;
	while(run--)//等等睡眠
	{
		vTaskDelay(10 / portTICK_RATE_MS);
		if(is_entry_sleep() == 0)//可以进入睡眠
		{
			system_entry_deep_sleep(60);//调整睡眠时间
		}
		else//没有休眠多等待一会
		{
			vTaskDelay(100 / portTICK_RATE_MS);
		}
	}
	system_entry_deep_sleep(60);//调整睡眠时间,直接休眠
}


void wait_got_ip_process()
{
	u16_t run = 0;
	u8_t NoApNum = 0;
	STATION_STATUS  getState;
	
  do
  {	
    vTaskDelay((100+NoApNum*10) / portTICK_RATE_MS);
    getState = wifi_station_get_connect_status();
    //printf("WIFI Status %d\r\n",getState);
    if(STATION_NO_AP_FOUND == getState)
   	{
			NoApNum++;
			printf("No AP SSID %d\r\n",NoApNum);
			if(NoApNum >= NO_AP_MAX_NUM)//没有AP最大数量
			{
				wifi_station_disconnect();//连不上路由器了，不重连
				if(is_update_NoAP_hint() == TRUE)//需要提示连不上路由器
				{
					send_epd_mail(EPD_EVT_SIMAlA);//显示连不上基站
					set_rtc_system_event_bit(EVT_NOAP_HINT,TRUE);//不能连接路由器直接提示标记
				}
				exception_process_entry_sleep(run,RLINK_AP_MAX_NUM);
			}
		}
		else if(STATION_WRONG_PASSWORD == getState)
		{
			wifi_station_disconnect();//连不上路由器了，不重连
			if(is_update_NoAP_hint() == TRUE)//需要提示连不上路由器
			{
				printf("PASSWORD WRONG !!!\r\n");
				send_epd_mail(EPD_EVT_SIMAlA);//显示连不上基站
				set_rtc_system_event_bit(EVT_NOAP_HINT,TRUE);//不能连接路由器直接提示标记
			}
			exception_process_entry_sleep(run,RLINK_AP_MAX_NUM);
		}
		else
		{
			NoApNum = 0;
		}
    run++;
    if(run == RLINK_AP_MAX_NUM)//30/2=15S 链接基站失败
    {
      if(is_key_evt_wakeup())//按键唤醒
      {
        send_epd_mail(EPD_EVT_SIMAlA);//显示连不上基站
        set_rtc_system_event_bit(EVT_NOAP_HINT,TRUE);//不能连接路由器直接提示标记
      }
      else //自动唤醒
      {
        while(run--)//进入睡眠
        {
          getState = wifi_station_get_connect_status();
          vTaskDelay(100 / portTICK_RATE_MS);
          if(is_entry_sleep() == 0)//可以睡眠
          {
            if(getState == STATION_CONNECTING)//一直在链接中
            {
            	printf("connecting ....\r\n");
              ask_evt_result_process(FAIL);
              system_entry_deep_sleep(60);//调整睡眠时间
            }
            else if(getState == STATION_GOT_IP)//突然获取到IP
            {
            	printf("Got IP OK1\r\n");
              break;
            }
            else//密码错误      链接AP失败      密码错误
            {
            	printf("PASSWORD WRONG2 !!!\r\n");
              system_entry_deep_sleep(60);//进入休眠，以60s累计
            }
          }
        }
				printf("run error not entry sleep\r\n");
				wifi_station_disconnect();//连不上路由器了，不重连
				if(is_update_NoAP_hint() == TRUE)//需要提示连不上路由器
				{
					send_epd_mail(EPD_EVT_SIMAlA);//显示连不上基站
					set_rtc_system_event_bit(EVT_NOAP_HINT,TRUE);//不能连接路由器直接提示标记
				}
        exception_process_entry_sleep(run,RLINK_AP_MAX_NUM);
      }
    }
    else if(run > RLINK_AP_MAX_NUM)//超时了
    {
      getState = wifi_station_get_connect_status();
      if(is_entry_sleep() == 0)//可以睡眠
      {
        if(getState == STATION_CONNECTING)//一直在链接中
        {
        	printf("connecting not got ip\r\n");
          ask_evt_result_process(FAIL);
          system_entry_deep_sleep(60);//调整睡眠时间
        }
        else if(getState == STATION_GOT_IP)//突然获取到IP
        {
        	printf("Got IP OK2\r\n");
          break;
        }
        else//密码错误      链接AP失败      密码错误
        {
        	printf("PASSWORD WRONG3 !!!\r\n");
          system_entry_deep_sleep(60);//进入休眠，以60s累计
        }
      }
			else
			{
				printf("run error not entry sleep\r\n");
				wifi_station_disconnect();//连不上路由器了，不重连
				if(is_update_NoAP_hint() == TRUE)//需要提示连不上路由器
				{
					send_epd_mail(EPD_EVT_SIMAlA);//显示连不上基站
					set_rtc_system_event_bit(EVT_NOAP_HINT,TRUE);//不能连接路由器直接提示标记
				}
				exception_process_entry_sleep(run,RLINK_AP_MAX_NUM);
			}
      //break;
    }
  }
  while (getState != STATION_GOT_IP);
}

void ICACHE_FLASH_ATTR
mainTaks(void *pvParameters)
{
  devinfo_init_process();//初始化设备信息

  sleep_wakeup_is();  //判断是否继续休眠

  vbat_low_stop_process(); //电压达到停止工作标准

  setHostName(); //设置主机名

  epd_show_thread_init();//启动显示线程

  //显示上次的图片
  //reloadFlashPicShow();
  wifiInitProcess();
  printf("Wait Got IP ...\n");

	wait_got_ip_process();
	
  get_wifi_intension();//获取WIFI信号强度
  protocol_thread_init();
  {
    vTaskDelay(1000 / portTICK_RATE_MS);
  }
  vTaskDelete(NULL);
}


void appCoreInit(void)
{
  gpio16_output_conf();
  gpio16_output_set(1);

  wifi_set_sleep_type(LIGHT_SLEEP_T);
  spiffs_fs1_init();//初始化文件系统

  printf("CPU ID = %d CPU Freq = %d\r\n",system_get_chip_id(),system_get_cpu_freq());//芯片ID

  xTaskCreate(mainTaks, "main", 1024, NULL, 3, NULL);
}




